package is.web.xdumper.client;

import is.bean.entity.department.Department;
import is.bean.entity.employee.Employee;
import is.bean.entity.region.Region;
import is.bean.stateless.xdumper.XdumperBeanRemote;
import is.bean.stateless.xdumper.XdumperBeanRemoteHome;
import is.xdumper.XdumperNoPathException;
import is.xdumper.type.Dump;
import is.xdumper.type.Entity;
import java.io.*;
import java.rmi.RemoteException;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.ejb.CreateException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
import javax.servlet.http.HttpServletRequest;

/**
 *
 * @author aspr0
 */
public abstract class XdumperClientRoutines
{
    protected Dump dump;
    protected Dump dumpRewrite;
    protected HttpServletRequest request;
    protected XdumperBeanRemote xdumper;
    protected XdumperClientSession clientSession;

    public XdumperClientRoutines() throws CreateException, RemoteException, NamingException
    {
        dump = new Dump();

//        XdumperBeanRemoteHome xdHome = (XdumperBeanRemoteHome) new InitialContext().lookup("ejb/XdumperBean");

        Object xdRef = new InitialContext().lookup("ejb/XdumperBean");
        XdumperBeanRemoteHome xdHome =
                (XdumperBeanRemoteHome) PortableRemoteObject.narrow(xdRef, XdumperBeanRemoteHome.class);

        xdumper = xdHome.create();

        clientSession = new XdumperClientSession();
    }

    public void setRequest(HttpServletRequest request)
    {
        this.request = request;
    }

    @Deprecated
    protected Entity getEntityToDump()
    {
        if (paramEquals("entity", "employee"))
        {
            return Entity.EMPLOYEE;
        }
        else if (paramEquals("entity", "department"))
        {
            return Entity.DEPARTMENT;
        }
        else if (paramEquals("entity", "region"))
        {
            return Entity.REGION;
        }
        else
        {
            return null;
        }
    }

    protected boolean getDumpReferences()
    {
        if (paramEquals("dumpReferences", "1"))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    /**
     * Collect items selected on "dump items" step into dump field
     */
    protected void collectDumpItems() throws XdumperNoDumpItemsException
    {
        int idsCount;

        Set<Department> departmentTable = new HashSet<Department>();
        Set<Employee> employeeTable = new HashSet<Employee>();
        Set<Region> regionTable = new HashSet<Region>();

        try
        {
            idsCount = Integer.parseInt(request.getParameter("idsCount"));
        }
        catch (NumberFormatException e)
        {
            throw new XdumperNoDumpItemsException();
        }

        for (int idNum = 0; idNum < idsCount; idNum++)
        {
            try
            {
                Integer id = Integer.parseInt(request.getParameter("id" + idNum));

                switch (dump.getMajorEntity())
                {
                    case DEPARTMENT:
                        Department d = new Department();
                        d.setId(id);
                        departmentTable.add(d);
                        break;

                    case EMPLOYEE:
                        Employee e = new Employee();
                        e.setId(id);
                        employeeTable.add(e);
                        break;

                    case REGION:
                        Region r = new Region();
                        r.setId(id);
                        regionTable.add(r);
                        break;
                }
            }
            catch (NumberFormatException e)
            {
                continue;
            }
        }

        switch (dump.getMajorEntity())
        {
            case DEPARTMENT:
                if (departmentTable.size() < 1)
                {
                    throw new XdumperNoDumpItemsException();
                }
                break;

            case EMPLOYEE:
                if (employeeTable.size() < 1)
                {
                    throw new XdumperNoDumpItemsException();
                }
                break;

            case REGION:
                if (regionTable.size() < 1)
                {
                    throw new XdumperNoDumpItemsException();
                }
                break;
        }

        dump.setDepartmentTable(departmentTable);
        dump.setEmployeeTable(employeeTable);
        dump.setRegionTable(regionTable);
    }

    protected boolean paramEquals(String paramName, String value)
    {
        if (value.equals(request.getParameter(paramName)))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    protected String getDateString()
    {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss");
        return dateFormat.format(new Date());
    }

    protected void serializeDumps(String fileName, String fileNameR) throws IOException, NamingException,
                                                                            RemoteException, XdumperNoPathException
    {
        FileOutputStream tmpStream = new FileOutputStream(XdumperClientConf.getPathOutputDirTmp() + fileName);
        ObjectOutputStream tmpObjectStream = new ObjectOutputStream(tmpStream);
        tmpObjectStream.writeObject(dump);
        tmpObjectStream.close();
        tmpStream.close();

        FileOutputStream tmpStreamR = new FileOutputStream(XdumperClientConf.getPathOutputDirTmp() + fileNameR);
        ObjectOutputStream tmpObjectStreamR = new ObjectOutputStream(tmpStreamR);
        tmpObjectStreamR.writeObject(dumpRewrite);
        tmpObjectStreamR.close();
        tmpStreamR.close();
    }

    protected void unserializeDumps(String fileName, String fileNameR) throws IOException, ClassNotFoundException,
                                                                              NamingException, RemoteException,
                                                                              XdumperNoPathException
    {
        FileInputStream tmpStream = new FileInputStream(XdumperClientConf.getPathOutputDirTmp() + fileName);
        ObjectInputStream tmpObjectStream = new ObjectInputStream(tmpStream);
        dump = (Dump) tmpObjectStream.readObject();
        tmpObjectStream.close();
        tmpStream.close();

        FileInputStream tmpStreamR = new FileInputStream(XdumperClientConf.getPathOutputDirTmp() + fileNameR);
        ObjectInputStream tmpObjectStreamR = new ObjectInputStream(tmpStreamR);
        dumpRewrite = (Dump) tmpObjectStreamR.readObject();
        tmpObjectStreamR.close();
        tmpStreamR.close();
    }

    protected void collectRewriteItems()
    {
        int idMax = Integer.parseInt(request.getParameter("maxid"));
        String idPref;
        int id;

        Set<Department> departmentTable = dump.getDepartmentTable();
        Set<Employee> employeeTable = dump.getEmployeeTable();
        Set<Region> regionTable = dump.getRegionTable();

        Set<Department> departmentTableR = dumpRewrite.getDepartmentTable();
        Set<Employee> employeeTableR = dumpRewrite.getEmployeeTable();
        Set<Region> regionTableR = dumpRewrite.getRegionTable();

        Iterator<Department> departmentsR = departmentTableR.iterator();
        Iterator<Employee> employeesR = employeeTableR.iterator();
        Iterator<Region> regionsR = regionTableR.iterator();

        for (int idNum = 1; idNum <= idMax; idNum++)
        {
            /* Removing unused old items */
            /* Departments */
            try
            {
                idPref = "d";
                id = Integer.parseInt(request.getParameter(idPref + idNum));

                while (departmentsR.hasNext())
                {
                    Department departmentR = departmentsR.next();
                    if (departmentR.getId().equals(id))
                    {
                        departmentsR.remove(); //todo consider using remove() on iterator further!
                        break;
                    }
                }
            }
            catch (NumberFormatException e)
            {
            }

            /* Employees */
            try
            {
                idPref = "e";
                id = Integer.parseInt(request.getParameter(idPref + idNum));

                while (employeesR.hasNext())
                {
                    Employee employeeR = employeesR.next();
                    if (employeeR.getId().equals(id))
                    {
                        employeesR.remove();
                        break;
                    }
                }
            }
            catch (NumberFormatException e)
            {
            }

            /* Regions */
            try
            {
                idPref = "r";
                id = Integer.parseInt(request.getParameter(idPref + idNum));

                while (regionsR.hasNext())
                {
                    Region regionR = regionsR.next();
                    if (regionR.getId().equals(id))
                    {
                        regionsR.remove();
                        break;
                    }
                }
            }
            catch (NumberFormatException e)
            {
            }
        }

        /* Removing new items, rewriting with old ones */
        /* Departments */
        Iterator<Department> departments = departmentTable.iterator();
        departmentsR = departmentTableR.iterator();
        while (departmentsR.hasNext())
        {
            Department departmentR = departmentsR.next();

            while (departments.hasNext())
            {
                Department department = departments.next();
                if (department.getId().equals(departmentR.getId()))
                {
                    departments.remove();
                    break;
                }
            }
        }
        departmentsR = departmentTableR.iterator();
        while (departmentsR.hasNext())
        {
            Department departmentR = departmentsR.next();
            departmentTable.add(departmentR);
        }

        /* Employees */
        Iterator<Employee> employees = employeeTable.iterator();
        employeesR = employeeTableR.iterator();
        while (employeesR.hasNext())
        {
            Employee employeeR = employeesR.next();

            while (employees.hasNext())
            {
                Employee employee = employees.next();
                if (employee.getId().equals(employeeR.getId()))
                {
                    employees.remove();
                    break;
                }
            }
        }
        employeesR = employeeTableR.iterator();
        while (employeesR.hasNext())
        {
            Employee employeeR = employeesR.next();
            employeeTable.add(employeeR);
        }

        /* Regions */
        Iterator<Region> regions = regionTable.iterator();
        regionsR = regionTableR.iterator();
        while (regionsR.hasNext())
        {
            Region regionR = regionsR.next();

            while (regions.hasNext())
            {
                Region region = regions.next();
                if (region.getId().equals(regionR.getId()))
                {
                    regions.remove();
                    break;
                }
            }
        }
        regionsR = regionTableR.iterator();
        while (regionsR.hasNext())
        {
            Region regionR = regionsR.next();
            regionTable.add(regionR);
        }

        dump.setDepartmentTable(departmentTable);
        dump.setEmployeeTable(employeeTable);
        dump.setRegionTable(regionTable);
    }

    protected String saveImportFile(String dumpXml) throws IOException, NamingException, RemoteException,
                                                         XdumperNoPathException
    {
        String dumpFileName = String.format("isbdx-dump.%s.%s.xml", "IMPORT", getDateString());
        File dumpFile = new File(XdumperClientConf.getPathOutputDir() + dumpFileName);
        FileWriter fw = new FileWriter(dumpFile);
        fw.write(dumpXml);
        fw.close();

        return dumpFileName;
    }
}
